//+------------------------------------------------------------------+
//|                                                  ZigZagUtils.mqh |
//|                        Copyright 2024, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Software Corp."
#property strict
#include <Trade\Trade.mqh>

input int      StopLossPoints = 10000;       // 止损点数
input int      TakeProfitPoints = 200;     // 止盈点数
input double   Lots = 0.01;                 // 交易手数
input ulong    MagicNumber = 12345;       // EA魔术号
input int      FastMAPeriod = 2;          // 快线周期
input int      SlowMAPeriod = 4;         // 慢线周期
input int      limtOrder = 5;             // 开单数量

int fastMA, slowMA;

CTrade trade;
//+------------------------------------------------------------------+
//| 定义存储高低点的结构体                                           |
//+------------------------------------------------------------------+
struct ZigZagPeaks
  {
   double            currentHigh;   // 当前高点
   double            prevHigh;      // 前一个高点
   double            currentLow;    // 当前低点
   double            prevLow;       // 前一个低点
  };


//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {

   fastMA = iMA(_Symbol, PERIOD_CURRENT, FastMAPeriod, 0, MODE_SMA, PRICE_CLOSE);
   slowMA = iMA(_Symbol, PERIOD_CURRENT, SlowMAPeriod, 0, MODE_SMA, PRICE_CLOSE);
   return(INIT_SUCCEEDED);
  }


//+------------------------------------------------------------------+
//| 获取最新两个有效高点和低点                                       |
//+------------------------------------------------------------------+
ZigZagPeaks GetZigZagPeaks(int depth=12, int deviation=5, int backstep=3)
  {
   ZigZagPeaks peaks = {0,0,0,0};
   int handle = iCustom(NULL, 0, "Examples\\ZigZag", depth, deviation, backstep);

   if(handle == INVALID_HANDLE)
     {
      Print("ZigZag指标初始化失败");
      return peaks;
     }

// 获取高低点数组
   double highs[], lows[];
   ArraySetAsSeries(highs, true);
   ArraySetAsSeries(lows, true);

// 复制足够的数据（建议至少100个柱）
   int copied = CopyBuffer(handle, 1, 0, 100, highs);  // 高点缓冲区
   copied     = CopyBuffer(handle, 2, 0, 100, lows);   // 低点缓冲区

   if(copied < 2)
     {
      Print("数据不足，至少需要2个有效点");
      return peaks;
     }

// 查找有效高点
   int highCount = 0;
   for(int i=copied-1; i>=0; i--)
     {
      if(highs[i] > 0 && highs[i] != EMPTY_VALUE)
        {
         if(highCount == 0)
           {
            peaks.currentHigh = highs[i];
            highCount++;
           }
         else
            if(highCount == 1)
              {
               peaks.prevHigh = highs[i];
               break;
              }
        }
     }

// 查找有效低点
   int lowCount = 0;
   for(int i=copied-1; i>=0; i--)
     {
      if(lows[i] > 0 && lows[i] != EMPTY_VALUE)
        {
         if(lowCount == 0)
           {
            peaks.currentLow = lows[i];
            lowCount++;
           }
         else
            if(lowCount == 1)
              {
               peaks.prevLow = lows[i];
               break;
              }
        }
     }

// 释放指标句柄
   IndicatorRelease(handle);

   return peaks;
  }

//+------------------------------------------------------------------+
//| 开多单（增加持仓检查）                                           |
//+------------------------------------------------------------------+
void OpenBuyPosition()
  {
// 检查是否已有持仓
//if(PositionSelect(_Symbol)) return;
   if(PositionsTotal()>=limtOrder)
     {
      return;
     }

   double price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   double sl = price - StopLossPoints * _Point;
   double tp = price + TakeProfitPoints * _Point;
   trade.PositionOpen(_Symbol, ORDER_TYPE_BUY, Lots, price, sl, tp, "Golden Cross Entry");
  }

//+------------------------------------------------------------------+
//| 平所有仓位                                                       |
//+------------------------------------------------------------------+
void CloseAllPositions()
  {
   for(int i = PositionsTotal()-1; i >= 0; i--)
     {
      ulong ticket = PositionGetTicket(i);
      if(PositionGetString(POSITION_SYMBOL) == _Symbol)
        {
         double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
         double currentSL = PositionGetDouble(POSITION_SL);
         double currentTP = PositionGetDouble(POSITION_TP);
         double currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID);
         double requiredPrice = openPrice;
         Print("档期：currentPrice",currentPrice);
         Print("档期：currentPrice",requiredPrice);
         if(currentPrice-openPrice>100*_Point)
           {
            double newSl=NormalizeDouble(currentPrice-50*_Point,_Digits);
            trade.PositionModify(_Symbol,newSl,0);
           }
         if(currentPrice/requiredPrice > 1.0009)
           {
            trade.PositionClose(ticket);
           }
        }
     }
  }


//+------------------------------------------------------------------+
//| 使用示例                                                        |
//+------------------------------------------------------------------+
void OnTick()
  {
   ZigZagPeaks zz = GetZigZagPeaks();

   Print("当前结构：");
   PrintFormat("最新高点: %.5f", zz.currentHigh);
   PrintFormat("前一个高点: %.5f", zz.prevHigh);
   PrintFormat("最新低点: %.5f", zz.currentLow);
   PrintFormat("前一个低点: %.5f", zz.prevLow);

// 获取均线值
   double  fastMAValues[3], slowMAValues[3];
//CopyBuffer(ssfastMA, 0, 1, 2, ssfastMAValues);
   CopyBuffer(fastMA, 0, 1, 2, fastMAValues);
   CopyBuffer(slowMA, 0, 1, 2, slowMAValues);
   ArraySetAsSeries(fastMAValues, true);
   ArraySetAsSeries(slowMAValues, true);


// 检查交叉信号
   bool goldenCross = (fastMAValues[1] > slowMAValues[1]) && (fastMAValues[0] <= slowMAValues[0]);
   bool deathCross = (fastMAValues[1] < slowMAValues[1]) && (fastMAValues[0] >= slowMAValues[0]);




   if(zz.currentHigh > zz.prevHigh && zz.currentLow > zz.prevLow)
     {
      Print("上升趋势：高点和低点均抬高");
      if(goldenCross)
        {
         OpenBuyPosition();
        }

     }
   else
      if(zz.currentHigh < zz.prevHigh && zz.currentLow < zz.prevLow)
        {
         Print("下降趋势：高点和低点均降低");
         CloseAllPositions();
        }
      else
        {
         Print("震荡行情");
        }
  }
//+------------------------------------------------------------------+
